using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.Xml.Xsl;
using OpenComposite.Base.Collections;
using OpenComposite.Mapper;
using OpenComposite.Repository.Properties;

namespace OpenComposite.EII.Repository
{
	[RepositoryItem(ItemType.LogicalActivity, "logical_activities", "log_act_id")]
	public class LogicalActivity : RepositoryItemBaseEx
	{
		#region Initialization
		/// <summary>
		/// Initializes a new instance of the <see cref="LogicalActivity"/> class.
		/// </summary>
		public LogicalActivity()
			: base("log_act_id", "log_act_nm", "log_act_desc", "log_act_ntext", Resources.sNewLogicalActivity)
		{
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="LogicalActivity"/> class.
		/// </summary>
		/// <param name="bCreateNew">if set to <c>true</c> [b create new].</param>
		public LogicalActivity(bool bCreateNew)
			: this()
		{
			if ( bCreateNew )
				this.CreateNew();
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="LogicalActivity"/> class.
		/// </summary>
		/// <param name="id">The id.</param>
		public LogicalActivity(int id)
			: this()
		{
			this.Load(id);
		}
		#endregion

		#region RepositoryItemBaseEx override

		/// <summary>
		/// Gets the image key.
		/// </summary>
		/// <value>The image key.</value>
		public override string ImageKey
		{
			get { return "service"; }
		}
		/// <summary>
		/// Gets the selected image key.
		/// </summary>
		/// <value>The selected image key.</value>
		public override string SelectedImageKey
		{
			get { return this.ImageKey; }
		}

		/// <summary>
		/// Gets the image.
		/// </summary>
		/// <value>The image.</value>
		public override System.Drawing.Image Image
		{
			get
			{
				Bitmap bmp = Resources.ico_or.ToBitmap();
				switch ( this.LogicalActivityType ) {
					case LogicalActivityType.LogicalOperation:
						bmp = Resources.png_logact_sync;
						break;
					case LogicalActivityType.LogicalCapability:
						bmp = Resources.png_logact_sync;
						break;
					case LogicalActivityType.DataAggregator:
						bmp = Resources.bmp_mapping;
						bmp.MakeTransparent(Color.Magenta);
						break;
					case LogicalActivityType.RuleEvaluator:
						bmp = Resources.png_brule;
						break;
					case LogicalActivityType.LogicalMethodCall:
						bmp = Resources.method;
						break;
					case LogicalActivityType.LogicalInput:
						bmp = Resources.png_event;
						break;
					case LogicalActivityType.Notification:
						bmp = Resources.ico_message.ToBitmap();
						break;
				}
				return bmp;
			}
		}
		/// <summary>
		/// Gets the selected image.
		/// </summary>
		/// <value>The selected image.</value>
		public override System.Drawing.Image SelectedImage
		{
			get { return this.Image; }
		}

		/// <summary>
		/// Gets the type of the repository item.
		/// </summary>
		/// <value>The type of the repository item.</value>
		public override ItemType RepositoryItemType
		{
			get { return ItemType.LogicalActivity; }
		}
		/// <summary>
		/// Gets the name of the repository item type.
		/// </summary>
		/// <value>The name of the repository item type.</value>
		public override string RepositoryItemTypeName
		{
			get { return Resources.sLogicalActivity; }
		}
		/// <summary>
		/// Gets the repository item type description.
		/// </summary>
		/// <value>The repository item type description.</value>
		public override string RepositoryItemTypeDescription
		{
			get { return ""; }
		}

		/// <summary>
		/// Gets the name of the table.
		/// </summary>
		/// <value>The name of the table.</value>
		public override string TableName
		{
			get { return "logical_activities"; }
		}

		/// <summary>
		/// Gets the allowed child types.
		/// </summary>
		/// <value>The allowed child types.</value>
		public override List<ItemType> AllowedChildTypes
		{
			get { return null; }
		}

		/// <summary>
		/// Saves this instance.
		/// </summary>
		/// <returns></returns>
		public override bool Save()
		{
			if ( _properties != null )
				setXmlSerializedObject("ExtendedProperties", "log_act_properties", _properties);

			return base.Save();
		}

		/// <summary>
		/// Copies this instance.
		/// </summary>
		/// <param name="deep"><c>true</c> to recursively copy the item and all subitems;
		/// <c>false</c> to copy only the item itself.</param>
		/// <returns>The copied item.</returns>
		public override IRepositoryItem Copy(bool deep)
		{
			return this.CopyInternal(deep, null);
		}
		public LogicalActivity CopyInternal(bool deep, Dictionary<int, int> mapBObjsOldNew)
		{
			LogicalActivity copy = new LogicalActivity(true);
			copy.InitializeServiceProvider(this);
			this.CopyDataRowToTarget(copy);
			// copy subscribed business objects
			NamedBusinessObjectCollection thisSubscribedBOs = this.GetSubscribedBusinessObjects();
			if ( thisSubscribedBOs != null ) {
				NamedBusinessObjectCollection subscribedBOs = new NamedBusinessObjectCollection();
				foreach ( var item in thisSubscribedBOs ) {
					NamedBusinessObject nbo = null;
					if ( mapBObjsOldNew != null ) {
						nbo = item.Copy(false);
						if ( nbo.BusinessObject != null ) {
							if ( mapBObjsOldNew.ContainsKey(nbo.BusinessObject.ID) ) {
								nbo.BusinessObject = Global.Repository.GetItem<BusinessObject>(
									mapBObjsOldNew[nbo.BusinessObject.ID]);
							} else {
								BusinessObject bo = nbo.BusinessObject.Copy(false) as BusinessObject;
								mapBObjsOldNew.Add(nbo.BusinessObject.ID, bo.ID);
								nbo.BusinessObject = bo;
							}
						}
					} else {
						nbo = item.Copy(deep);
					}
					if ( nbo != null ) subscribedBOs.Add(nbo);
				}
				copy.SetSubscribedBusinessObjects(subscribedBOs);
			}

			// copy published business objects
			NamedBusinessObjectCollection thisPublishedBOs = this.GetPublishedBusinessObjects();
			if ( thisPublishedBOs != null ) {
				List<BusinessObject> publishedBOs = new List<BusinessObject>();
				foreach ( var item in thisPublishedBOs ) {
					NamedBusinessObject nbo;
					if ( mapBObjsOldNew != null ) {
						nbo = item.Copy(false);
						if ( nbo.BusinessObject != null ) {
							if ( mapBObjsOldNew.ContainsKey(nbo.BusinessObject.ID) ) {
								nbo.BusinessObject = Global.Repository.GetItem<BusinessObject>(
									mapBObjsOldNew[nbo.BusinessObject.ID]);
							} else {
								BusinessObject bo = nbo.BusinessObject.Copy(true) as BusinessObject;
								mapBObjsOldNew.Add(nbo.BusinessObject.ID, bo.ID);
								nbo.BusinessObject = bo;
							}
						}
					} else {
						nbo = item.Copy(deep);
					}
					if ( nbo != null && nbo.BusinessObject != null ) {
						publishedBOs.Add(nbo.BusinessObject);
					}
				}
				copy.SetPublishedBusinessObjects(publishedBOs.ToArray());
			}

			return copy;
		}

		#endregion

		#region Public Members

		#region Properties

		public int VerbID
		{
			get { return getInt("log_act_verb_id", 0); }
			set { setValue("VerbID", "log_act_verb_id", value); }
		}
		/// <summary>
		/// Gets the assigned verb.
		/// </summary>
		/// <value>The assigned verb.</value>
		public Verb Verb
		{
			get
			{
				Verb cap = null;
				if ( this.VerbID > 0 ) {
					cap = this.RepositoryService.GetItem<Verb>(this.VerbID);
				}
				return cap;
			}
		}
		public int CompositeID
		{
			get { return getInt("log_act_svcmodule_id", 0); }
			set { setValue("CompositeID", "log_act_svcmodule_id", value); }
		}
		public int OperationID
		{
			get { return getInt("log_act_operation_id", 0); }
			set { setValue("OperationID", "log_act_operation_id", value); }
		}
		public int BusinessRuleID
		{
			get { return getInt("log_act_brule_id", -1); }
			set { setValue("BusinessRuleID", "log_act_brule_id", value); }
		}
		public int WorkflowMethodID
		{
			get { return getInt("log_act_wf_method_id", -1); }
			set { setValue("WorkflowMethodID", "log_act_wf_method_id", value); }
		}
		public int WorkflowEventID
		{
			get { return getInt("log_act_wf_event_id", -1); }
			set { setValue("WorkflowEventID", "log_act_wf_event_id", value); }
		}

		public int WorkflowID
		{
			get
			{
				if ( this.WorkflowMethodID > 0 ) {
					WorkflowMethod wm = this.GetWorkflowMethod();
					if ( wm != null ) return wm.WorkflowID;
				} else if ( this.WorkflowEventID > 0 ) {
					WorkflowEvent we = this.GetWorkflowEvent();
					if ( we != null ) return we.WorkflowID;
				}
				return getInt("workflow_id", -1);
			}
			set { setValue("WorkflowID", "workflow_id", value); }
		}
		public Workflow Workflow
		{
			get
			{
				if ( this.WorkflowID > 0 )
					return this.RepositoryService.GetItem(ItemType.Workflow, this.WorkflowID, false) as Workflow;
				else
					return null;
			}
			set { this.WorkflowID = ( value == null ? -1 : value.ID ); }
		}

		public int LogicalMethodID
		{
			get { return getInt("log_wmeth_id", -1); }
			set { setValue("LogicalMethodID", "log_wmeth_id", value); }
		}
		/// <summary>
		/// Gets or sets the logical method.
		/// </summary>
		/// <value>The logical method.</value>
		public LogicalWebMethod LogicalMethod
		{
			get
			{
				if ( this.LogicalMethodID > 0 )
					return this.RepositoryService.GetItem<LogicalWebMethod>(this.LogicalMethodID);
				else {
					Verb v = this.Verb;
					if ( v != null ) {
						this.LogicalMethodID = v.DefaultLogicalMethodID;
						this.Save();
						return this.RepositoryService.GetItem<LogicalWebMethod>(this.LogicalMethodID);
					} else {
						return null;
					}
				}
			}
			set { this.LogicalMethodID = ( value == null ? -1 : value.ID ); }
		}

		public int WebServiceID
		{
			get { return getInt("log_act_websvc_id", -1); }
			set { setValue("WebServiceID", "log_act_websvc_id", value); }
		}
		public int WebMethodID
		{
			get { return getInt("log_act_webmethod_id", -1); }
			set { setValue("WebMethodID", "log_act_webmethod_id", value); }
		}

		/// <summary>
		/// Gets or sets the display name. Temporary only! Not stored in DB
		/// </summary>
		/// <value>The display name.</value>
		public string DisplayName { get; set; }

		/// <summary>
		/// Gets or sets the human activity ID.
		/// </summary>
		/// <value>The human activity ID.</value>
		public int HumanActivityID
		{
			get { return getInt("log_act_hact_id", -1); }
			set { setValue("HumanActivityID", "log_act_hact_id", value); }
		}

		/// <summary>
		/// Gets or sets the input connections.
		/// </summary>
		/// <value>The input connections.</value>
		public string InputConnections
		{
			get { return getString("log_act_input_connections", null); }
			set { setValue("InputConnections", "log_act_input_connections", value); }
		}
		/// <summary>
		/// Gets or sets the input XSLT.
		/// </summary>
		/// <value>The input XSLT.</value>
		public XsltDocument InputXslt
		{
			get
			{
				string sXslt = getString("log_act_input_xslt", null);
				XsltDocument xslt = null;
				if ( !string.IsNullOrEmpty(sXslt) ) {
					xslt = new XsltDocument();
					xslt.LoadXml(sXslt);
				}
				return xslt;
			}
			set { setXmlDocument("InputXslt", "log_act_input_xslt", value); }
		}
		/// <summary>
		/// Gets or sets the output connections.
		/// </summary>
		/// <value>The output connections.</value>
		public string OutputConnections
		{
			get { return getString("log_act_output_connections", null); }
			set { setValue("OutputConnections", "log_act_output_connections", value); }
		}
		/// <summary>
		/// Gets or sets the output XSLT.
		/// </summary>
		/// <value>The output XSLT.</value>
		public XsltDocument OutputXslt
		{
			get
			{
				string sXslt = getString("log_act_output_xslt", null);
				XsltDocument xslt = null;
				if ( !string.IsNullOrEmpty(sXslt) ) {
					xslt = new XsltDocument();
					xslt.LoadXml(sXslt);
				}
				return xslt;
			}
			set { setXmlDocument("OutputXslt", "log_act_output_xslt", value); }
		}

		/// <summary>
		/// Gets a value indicating whether this instance has input business object.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if this instance has input business object; otherwise, <c>false</c>.
		/// </value>
		public bool HasInputBusinessObject
		{
			get
			{
				Verb verb = this.Verb;
				if ( verb != null )
					return ( verb.InputBusinessObjectID > 0 );
				else
					return ( this.InputBusinessObjectID > 0 );
			}
		}
		/// <summary>
		/// Gets or sets the input business object ID.
		/// </summary>
		/// <value>The input business object ID.</value>
		public int InputBusinessObjectID
		{
			get { return getInt("log_act_input_bobj_id", -1); }
			set { setValue("InputBusinessObjectID", "log_act_input_bobj_id", value); }
		}
		/// <summary>
		/// Gets the input business object.
		/// </summary>
		/// <value>The input business object.</value>
		public BusinessObject InputBusinessObject
		{
			get { return GetInputBusinessObject(); }
		}
		/// <summary>
		/// Gets the input business object schema.
		/// </summary>
		/// <value>The input business object schema.</value>
		public XmlSchema InputBusinessObjectSchema
		{
			get
			{
				BusinessObject bo = this.InputBusinessObject;
				return ( bo != null ? bo.Schema : null );
			}
		}
		/// <summary>
		/// Gets or sets the name of the input variable. 
		/// (This is only a reference to the InputVariableName in the ExtendedProperties)
		/// </summary>
		/// <value>The name of the input variable.</value>
		public string InputVariableName
		{
			get { return this.ExtendedProperties.InputVariableName; }
			set { this.ExtendedProperties.InputVariableName = value; }
		}

		public bool HasOutputBusinessObject
		{
			get { return this.OutputBusinessObject != null; }
		}
		public int OutputBusinessObjectID
		{
			get { return getInt("log_act_output_bobj_id", -1); }
			set { setValue("OutputBusinessObjectID", "log_act_output_bobj_id", value); }
		}
		private string _outputVarName = null;
		public string OutputVariableName
		{
			get
			{
				if ( !HasOutputBusinessObject ) throw new ArgumentException("Logical Activity has no output object!");
				if ( string.IsNullOrEmpty(_outputVarName) ) {
					_outputVarName = string.Format("{0}_{1}", this.Name, this.OutputBusinessObject.Name);
				}
				return _outputVarName;
			}
			set
			{
				if ( !HasOutputBusinessObject ) throw new ArgumentException("Logical Activity has no output object!");
				_outputVarName = value;
			}
		}
		public BusinessObject OutputBusinessObject
		{
			get { return GetOutputBusinessObject(); }
		}
		public XmlSchema OutputBusinessObjectSchema
		{
			get
			{
				BusinessObject bo = this.OutputBusinessObject;
				return ( bo != null ? bo.Schema : null );
			}
		}

		public string LogicalInputConnections
		{
			get { return getString("log_act_loginput_connections", null); }
			set { setValue("LogicalInputConnections", "log_act_loginput_connections", value); }
		}
		public string LogicalInputXslt
		{
			get { return getString("log_act_loginput_xslt", null); }
			set { setValue("LogicalInputXslt", "log_act_loginput_xslt", value); }
		}
		public string PhysicalInputConnections
		{
			get { return getString("log_act_physinput_connections", null); }
			set { setValue("PhysicalInputConnections", "log_act_physinput_connections", value); }
		}
		public string PhysicalInputXslt
		{
			get { return getString("log_act_physinput_xslt", null); }
			set { setValue("PhysicalInputXslt", "log_act_physinput_xslt", value); }
		}

		public LogicalActivityType LogicalActivityType
		{
			get { return (LogicalActivityType)getInt("log_act_type", 0); }
			set { setValue("LogicalActivityType", "log_act_type", (int)value); }
		}

		private LogicalActivityProperties _properties = null;
		public LogicalActivityProperties ExtendedProperties
		{
			get
			{
				if ( _properties == null ) {
					_properties = getXmlSerializedObject<LogicalActivityProperties>("log_act_properties");
					if ( _properties == null )
						_properties = new LogicalActivityProperties();
				}
				return _properties;
			}
		}
		#endregion

		#region Methods

		/// <summary>
		/// Gets the input business object.
		/// </summary>
		/// <returns></returns>
		public BusinessObject GetInputBusinessObject()
		{
			BusinessObject bo = null;
			Verb verb = this.Verb;
			WorkflowMethod wm = this.GetWorkflowMethod();
			if ( verb != null ) {
				bo = verb.InputBusinessObject;
			} else if ( this.InputBusinessObjectID > 0 ) {
				bo = this.RepositoryService.GetItem<BusinessObject>(this.InputBusinessObjectID);
				if ( bo != null && bo.IsDeleted )
					bo = null;
			} else if ( wm != null ) {
				bo = wm.InputBusinessObject;
			}
			return bo;
		}
		/// <summary>
		/// Gets the output business object.
		/// </summary>
		/// <returns></returns>
		public BusinessObject GetOutputBusinessObject()
		{
			BusinessObject bo = null;
			Verb verb = this.Verb;
			Operation op = this.GetAssignedOperation();
			WorkflowEvent we = this.GetWorkflowEvent();
			WorkflowMethod wm = this.GetWorkflowMethod();

			if ( verb != null ) {
				bo = verb.OutputBusinessObject;
			} else if ( op != null ) {
				bo = op.GetOutputBusinessObject();
			} else if ( this.OutputBusinessObjectID > 0 ) {
				bo = this.RepositoryService.GetItem<BusinessObject>(this.OutputBusinessObjectID);
				//bo.Reload();
				if ( bo != null && bo.IsDeleted )
					bo = null;
			} else if ( we != null ) {
				bo = we.BusinessObject;
			} else if ( wm != null ) {
				bo = wm.OutputBusinessObject;
			}
			return bo;
		}

		/// <summary>
		/// Gets the business rule.
		/// </summary>
		/// <returns></returns>
		public RepositoryBusinessRule GetBusinessRule()
		{
			return this.RepositoryService.GetItem<RepositoryBusinessRule>(this.BusinessRuleID);
		}

		/// <summary>
		/// Gets the web service.
		/// </summary>
		/// <returns></returns>
		public WebService GetWebService()
		{
			WebService ws = null;
			if ( this.WebServiceID > 0 ) {
				ws = this.RepositoryService.GetItem<WebService>(this.WebServiceID);
				if ( ws != null && ws.IsDeleted )
					ws = null;
			}
			return ws;
		}
		/// <summary>
		/// Gets the web method.
		/// </summary>
		/// <returns></returns>
		public WebMethod GetWebMethod()
		{
			WebMethod wm = null;
			if ( this.WebMethodID > 0 ) {
				wm = this.RepositoryService.GetItem<WebMethod>(this.WebMethodID);
				if ( wm != null && wm.IsDeleted )
					wm = null;
			}
			return wm;
		}

		/// <summary>
		/// Gets the workflow method.
		/// </summary>
		/// <returns></returns>
		public WorkflowMethod GetWorkflowMethod()
		{
			WorkflowMethod wm = null;
			if ( this.WorkflowMethodID > 0 ) {
				wm = this.RepositoryService.GetItem(ItemType.Workflow_Method, this.WorkflowMethodID, false)
					as WorkflowMethod;
			}
			return wm;
		}
		/// <summary>
		/// Gets the workflow event.
		/// </summary>
		/// <returns></returns>
		public WorkflowEvent GetWorkflowEvent()
		{
			WorkflowEvent we = null;
			if ( this.WorkflowEventID > 0 ) {
				we = this.RepositoryService.GetItem(ItemType.Workflow_Event, this.WorkflowEventID, false)
					as WorkflowEvent;
			}
			return we;
		}

		/// <summary>
		/// Gets the human activity.
		/// </summary>
		/// <returns></returns>
		public HumanActivity GetHumanActivity()
		{
			HumanActivity ha = null;
			if ( this.HumanActivityID > 0 ) {
				ha = this.RepositoryService.GetItem<HumanActivity>(this.HumanActivityID);
				if ( ha != null && ha.IsDeleted )
					ha = null;
			}
			return ha;
		}

		/// <summary>
		/// Gets the published business objects.
		/// </summary>
		/// <returns></returns>
		public NamedBusinessObjectCollection GetPublishedBusinessObjects()
		{
			return Global.Data.GetLogicalActivityBusinessObjects(this.ID, false);
		}
		/// <summary>
		/// Sets the published business objects.
		/// </summary>
		/// <param name="businessObjects">The business objects.</param>
		public void SetPublishedBusinessObjects(BusinessObject[] businessObjects)
		{
			Global.Data.RemoveAllBusinessObjectsFromLogicalActivity(this.ID, false);
			if ( businessObjects != null ) {
				foreach ( BusinessObject bo in businessObjects ) {
					AddPublishedBusinessObject(bo, this.ID);
				}
			}
		}
		/// <summary>
		/// Adds the published business object.
		/// </summary>
		/// <param name="bobject">The bobject.</param>
		/// <param name="publishedLogAct">The published log act.</param>
		public void AddPublishedBusinessObject(BusinessObject bobject, int publishedLogAct)
		{
			Global.Data.AddBusinessObjectToLogicalActivity(this.ID, bobject.ID, false, publishedLogAct);
		}
		/// <summary>
		/// Removes the published business object.
		/// </summary>
		/// <param name="bobject">The bobject.</param>
		public void RemovePublishedBusinessObject(NamedBusinessObject bobject)
		{
			Global.Data.RemoveBusinessObjectFromLogicalActivity(this.ID, bobject.BusinessObject.ID, false, bobject.LogicalActivity != null ? bobject.LogicalActivity.ID : -1);
		}
		/// <summary>
		/// Gets the mapped input object.
		/// </summary>
		/// <param name="subscribedObjects">The subscribed objects.</param>
		/// <returns></returns>
		public XmlDocument GetMappedInputObject(BindingListEx<object> subscribedObjects)
		{
			if ( this.InputXslt == null ) return null;
			if ( subscribedObjects == null ) return null;
			NamedBusinessObjectCollection subscribedBOs = GetSubscribedBusinessObjects();
			if ( subscribedBOs == null ) return null;
			if ( subscribedObjects.Count != subscribedBOs.Count ) throw new InvalidOperationException("Parameter does not match subscribed Busines Objects");

			XmlDocument xdCompound = new System.Xml.XmlDocument();
			xdCompound.AppendChild(xdCompound.CreateElement("tns", "SubscribedDocuments", "http://www.OpenComposite.com/canonical_document"));
			using ( MemoryStream msSubscribed = new MemoryStream() ) {
				for ( int i = 0; i < subscribedBOs.Count; i++ ) {
					object obj = subscribedObjects[i];
					NamedBusinessObject namedObj = subscribedBOs[i];
					if ( obj == null ) continue;
					using ( MemoryStream msInput = new MemoryStream() ) {
						XmlDocument xd = new XmlDocument();
						object[] attr = obj.GetType().GetCustomAttributes(typeof(DataContractAttribute), false);
						if ( attr.Length > 0 ) {
							DataContractSerializer xs;
							xs = new DataContractSerializer(obj.GetType());
							xs.WriteObject(msInput, obj);
						} else {
							XmlSerializer xs;
							xs = new XmlSerializer(obj.GetType(), "http://www.OpenComposite.com/canonical_document");
							xs.Serialize(msInput, obj);
						}
						msInput.Position = 0;
						xd.Load(msInput);
						System.Xml.XmlElement elem = xdCompound.CreateElement("tns", namedObj.Name, "http://www.OpenComposite.com/canonical_document");
						for ( int k = 0; k < xd.DocumentElement.ChildNodes.Count; k++ ) {
							elem.AppendChild(xdCompound.ImportNode(xd.DocumentElement.ChildNodes[k], true));
						}
						xdCompound.DocumentElement.AppendChild(elem);
					}
				}

				XslCompiledTransform xslt = new XslCompiledTransform();
				using ( StringReader srXSLT = new StringReader(this.InputXslt.InnerXml) )
				using ( XmlReader xrXSLT = XmlReader.Create(srXSLT) ) {
					xslt.Load(xrXSLT);
				}
				using ( MemoryStream msInput = new MemoryStream() ) {
					xdCompound.Save(msInput);
					msInput.Position = 0;
					msSubscribed.Position = 0;
					using ( XmlReader xrInput = XmlReader.Create(msInput) )
					using ( XmlWriter xwOutput = XmlWriter.Create(msSubscribed, xslt.OutputSettings) ) {
						xslt.Transform(xrInput, xwOutput);
						xwOutput.Flush();
						msSubscribed.Position = 0;
						StreamReader sr = new StreamReader(msSubscribed);
						string c = sr.ReadToEnd();
						msSubscribed.Position = 0;
						xdCompound.Load(msSubscribed);
					}
				}
			}
			return xdCompound;
		}
		/// <summary>
		/// Gets the subscribed business objects.
		/// </summary>
		/// <returns></returns>
		public NamedBusinessObjectCollection GetSubscribedBusinessObjects()
		{
			if ( this.LogicalActivityType == LogicalActivityType.LogicalInput ) {
				return null;
			} else {
				return Global.Data.GetLogicalActivityBusinessObjects(this.ID, true);
			}
		}
		/// <summary>
		/// Sets the subscribed business objects.
		/// </summary>
		/// <param name="subscribedItems">The subscribed items.</param>
		public void SetSubscribedBusinessObjects(NamedBusinessObjectCollection subscribedItems)
		{
			Global.Data.RemoveAllBusinessObjectsFromLogicalActivity(this.ID, true);
			if ( subscribedItems != null ) {
				foreach ( NamedBusinessObject item in subscribedItems ) {
					int id = item.LogicalActivity == null ? -1 : item.LogicalActivity.ID;
					AddSubscribedBusinessObject(item.BusinessObject, id);
				}
			}
		}
		/// <summary>
		/// Adds the subscribed business object.
		/// </summary>
		/// <param name="bobject">The bobject.</param>
		/// <param name="logAct">The log act.</param>
		public void AddSubscribedBusinessObject(BusinessObject bobject, int logAct)
		{
			Global.Data.AddBusinessObjectToLogicalActivity(this.ID, bobject.ID, true, logAct);
		}
		/// <summary>
		/// Removes the subscribed business object.
		/// </summary>
		/// <param name="bobject">The bobject.</param>
		public void RemoveSubscribedBusinessObject(NamedBusinessObject bobject)
		{
			Global.Data.RemoveBusinessObjectFromLogicalActivity(this.ID, bobject.BusinessObject.ID, true, bobject.LogicalActivity != null ? bobject.LogicalActivity.ID : -1);
		}

		/// <summary>
		/// Gets the subscribed compound XML schema.
		/// </summary>
		/// <returns></returns>
		public XmlSchema GetSubscribedCompoundXmlSchema()
		{
			NamedBusinessObjectCollection bos = this.GetSubscribedBusinessObjects();
			if ( bos == null || bos.Count == 0 )
				return null;
			List<XmlSchema> schemas = new List<XmlSchema>();
			foreach ( BusinessObject bo in bos.BusinessObjects ) {
				if ( bo.Schema != null )
					schemas.Add(bo.Schema);
			}
			return createCompoundDocument(schemas);
		}
		private XmlSchema createCompoundDocument(List<XmlSchema> schemas)
		{
			if ( schemas.Count == 0 ) {
				return null;
			}

			XmlSchemaSet xset = new XmlSchemaSet();

			//init Compound Schema
			XmlSchema compSchema = new XmlSchema();
			compSchema.ElementFormDefault = XmlSchemaForm.Qualified;
			compSchema.AttributeFormDefault = XmlSchemaForm.Qualified;
			compSchema.TargetNamespace = schemas[0].TargetNamespace;
			compSchema.Namespaces.Add("tns", "http://www.OpenComposite.com/canonical_document");
			compSchema.Namespaces.Add("xsd", "http://www.w3.org/2001/XMLSchema");

			//init choice-Element for adding Elements to the Schema
			XmlSchemaElement element = new XmlSchemaElement();
			element.Name = "SubscribedDocuments";
			XmlSchemaComplexType complexType = new XmlSchemaComplexType();
			element.SchemaType = complexType;
			XmlSchemaSequence seq = new XmlSchemaSequence();
			complexType.Particle = seq;

			int counter = 0;
			foreach ( XmlSchema schema in schemas ) {
				foreach ( XmlQualifiedName qname in schema.Namespaces.ToArray() ) {
					if ( qname.Namespace == "http://www.w3.org/2001/XMLSchema" ||
						 qname.Namespace == "http://www.OpenComposite.com/canonical_document" )
						continue;

					compSchema.Namespaces.Add(string.Format("compSch{0}", counter),
						qname.Namespace);
					counter++;
				}
				xset.Add(schema);
			}
			xset.Compile();
			if ( !xset.IsCompiled ) {
				throw new Exception("Compiling Schemas failed in FormLogicalActivityConfiguration.createCompoundDocument(..).");
			}
			for ( int i = 0; i < schemas.Count; i++ ) {
				foreach ( XmlSchemaObject schemaObj in schemas[i].Items ) {
					if ( schemaObj is XmlSchemaElement ) {
						bool exists = false;
						foreach ( XmlSchemaObject xmlObj in seq.Items ) {
							if ( xmlObj is XmlSchemaElement ) {
								if ( ( (XmlSchemaElement)xmlObj ).QualifiedName ==
									( (XmlSchemaElement)schemaObj ).QualifiedName ) {
									exists = true;
								}
							}
						}
						if ( exists == false ) {
							seq.Items.Add(schemaObj);
						}
					} else {
						if ( compSchema.Items.Contains(schemaObj) == false ) {
							compSchema.Items.Add(schemaObj);
						}
					}
				}
			}

			//add compound Element that contains the subscribed Elements
			if ( compSchema.Items.Contains(element) == false ) {
				compSchema.Items.Add(element);
			}

			xset = new XmlSchemaSet();
			xset.Add(compSchema);
			//xset.ValidationEventHandler += new ValidationEventHandler(this.validationEventHandler);
			xset.Compile();

			return compSchema;
		}
		/// <summary>
		/// Gets the assigned operation.
		/// </summary>
		/// <returns></returns>
		public Operation GetAssignedOperation()
		{
			Operation op = null;
			if ( this.OperationID > 0 ) {
				op = this.RepositoryService.GetItem<Operation>(this.OperationID);
			}
			return op;
		}

		/// <summary>
		/// Gets the icon.
		/// </summary>
		/// <returns></returns>
		public override Icon GetIcon()
		{
			return Resources.ico_delete_16x;
		}

		#region Logical Activity Bindings

		/// <summary>
		/// Sets the binding.
		/// </summary>
		/// <param name="binding">The binding.</param>
		public void SetBinding(LogicalActivityBinding binding)
		{
			binding.LogicalActivityID = this.ID;
			Global.Data.SetLogicalActivityBinding(binding);
		}
		/// <summary>
		/// Deletes the binding.
		/// </summary>
		/// <param name="binding">The binding.</param>
		public void DeleteBinding(LogicalActivityBinding binding)
		{
			Global.Data.DeleteLogicalActivityBinding(this.ID, binding.WebServiceID, binding.WebMethodID);
		}

		/// <summary>
		/// Gets the bindings.
		/// </summary>
		/// <returns></returns>
		public BindingListEx<LogicalActivityBinding> GetBindings()
		{
			return Global.Data.GetLogicalActivityBindings(this);
		}

		#endregion

		#endregion

		#endregion

		#region Protected Members

		#region Methods
		// override
		/// <summary>
		/// Called when [item deleting].
		/// </summary>
		protected override void OnItemDeleting()
		{
			base.OnItemDeleting();
			this.WorkflowEventID = -1;
			this.WorkflowMethodID = -1;
		}
		#endregion

		#endregion

		#region Class: LogicalActivityProperties
		[Serializable]
		[XmlRoot(Namespace = "http://www.OpenComposite.com/Repository")]
		[XmlType(Namespace = "http://www.OpenComposite.com/Repository")]
		[TypeConverter(typeof(ExpandableObjectConverter))]
		public class LogicalActivityProperties
		{
			private string _bruleOutputPath;
			/// <summary>
			/// Gets or sets the business rule output path.
			/// </summary>
			/// <value>The business rule output path.</value>
			public string BusinessRuleOutputPath
			{
				get { return _bruleOutputPath; }
				set { _bruleOutputPath = value; }
			}

			private HumanComponentProperties _haprops = null;
			/// <summary>
			/// Gets or sets the human component properties.
			/// </summary>
			/// <value>The human component properties.</value>
			public HumanComponentProperties HumanComponentProperties
			{
				get
				{
					if ( _haprops == null ) {
						_haprops = new HumanComponentProperties();
					}
					return _haprops;
				}
				set { _haprops = value; }
			}

			/// <summary>
			/// Gets or sets a value indicating whether [use code mapping].
			/// </summary>
			/// <value><c>true</c> if [use code mapping]; otherwise, <c>false</c>.</value>
			[DefaultValue(false)]
			public bool UseCodeMapping { get; set; }
			/// <summary>
			/// Gets or sets the input code mapping.
			/// </summary>
			/// <value>The input code mapping.</value>
			public string InputCodeMapping { get; set; }
			/// <summary>
			/// Gets or sets the output code mapping.
			/// </summary>
			/// <value>The output code mapping.</value>
			public string OutputCodeMapping { get; set; }

			/// <summary>
			/// Gets or sets the name of the input variable.
			/// </summary>
			/// <value>The name of the input variable.</value>
			public string InputVariableName { get; set; }
		}
		#endregion
	}

	#region Enum: LogicalActivityType
	public enum LogicalActivityType
	{
		Undefined = 0,
		LogicalOperation,
		LogicalCapability,
		DataAggregator,
		RuleEvaluator,
		LogicalMethodCall,
		LogicalInput,
		Notification
	}
	#endregion

	#region Class: LogicalActivityBinding
	public class LogicalActivityBinding
	{
		#region Initialization
		/// <summary>
		/// Initializes a new instance of the <see cref="LogicalActivityBinding"/> class.
		/// </summary>
		/// <param name="serviceProvider">The service provider.</param>
		public LogicalActivityBinding(IServiceProvider serviceProvider)
		{
			_serviceProvider = serviceProvider;
		}
		#endregion

		#region Private Fields
		private int log_act_id;
		private int websvc_id;
		private int webmethod_id;
		private int hact_id;
		private string input_connections;
		private XsltDocument input_xslt;
		private string output_connections;
		private XsltDocument output_xslt;
		private LogicalActivity.LogicalActivityProperties properties;

		private IServiceProvider _serviceProvider;
		#endregion

		/// <summary>
		/// Gets or sets the logical activity ID.
		/// </summary>
		/// <value>The logical activity ID.</value>
		public int LogicalActivityID
		{
			get { return log_act_id; }
			set { log_act_id = value; }
		}
		/// <summary>
		/// Gets or sets the web service ID.
		/// </summary>
		/// <value>The web service ID.</value>
		public int WebServiceID
		{
			get { return websvc_id; }
			set { websvc_id = value; }
		}
		/// <summary>
		/// Gets or sets the web method ID.
		/// </summary>
		/// <value>The web method ID.</value>
		public int WebMethodID
		{
			get { return webmethod_id; }
			set { webmethod_id = value; }
		}
		/// <summary>
		/// Gets or sets the human activity ID.
		/// </summary>
		/// <value>The human activity ID.</value>
		public int HumanActivityID
		{
			get { return hact_id; }
			set { hact_id = value; }
		}
		/// <summary>
		/// Gets or sets the input connections.
		/// </summary>
		/// <value>The input connections.</value>
		public string InputConnections
		{
			get { return input_connections; }
			set { input_connections = value; }
		}
		/// <summary>
		/// Gets or sets the input XSLT.
		/// </summary>
		/// <value>The input XSLT.</value>
		public XsltDocument InputXslt
		{
			get { return input_xslt; }
			set { input_xslt = value; }
		}
		/// <summary>
		/// Gets or sets the output connections.
		/// </summary>
		/// <value>The output connections.</value>
		public string OutputConnections
		{
			get { return output_connections; }
			set { output_connections = value; }
		}
		/// <summary>
		/// Gets or sets the output XSLT.
		/// </summary>
		/// <value>The output XSLT.</value>
		public XsltDocument OutputXslt
		{
			get { return output_xslt; }
			set { output_xslt = value; }
		}
		/// <summary>
		/// Gets or sets the extended properties.
		/// </summary>
		/// <value>The extended properties.</value>
		public LogicalActivity.LogicalActivityProperties ExtendedProperties
		{
			get { return properties; }
			set { properties = value; }
		}
		/// <summary>
		/// Gets a value indicating whether this instance is deleted.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if this instance is deleted; otherwise, <c>false</c>.
		/// </value>
		public bool IsDeleted
		{
			get
			{
				bool deleted = false;
				RepositoryService rs = (RepositoryService)_serviceProvider.GetService(typeof(RepositoryService));
				Debug.Assert(rs != null);
				WebService ws = rs.GetItem<WebService>(this.WebServiceID);
				WebMethod wm = rs.GetItem<WebMethod>(this.WebMethodID);
				if ( ws == null || wm == null )
					deleted = true;
				return deleted;
			}
		}

		/// <summary>
		/// Returns a <see cref="System.String"/> that represents this instance.
		/// </summary>
		/// <returns>
		/// A <see cref="System.String"/> that represents this instance.
		/// </returns>
		public override string ToString()
		{
			RepositoryService rs = (RepositoryService)_serviceProvider.GetService(typeof(RepositoryService));
			Debug.Assert(rs != null);
			WebService ws = rs.GetItem<WebService>(this.WebServiceID);
			WebMethod wm = rs.GetItem<WebMethod>(this.WebMethodID);
			if ( ws != null && wm != null )
				return ws.Name + " - " + wm.Name;
			else
				return "DELETED";
		}
		/// <summary>
		/// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
		/// </summary>
		/// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
		/// <returns>
		/// 	<c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
		/// </returns>
		/// <exception cref="T:System.NullReferenceException">
		/// The <paramref name="obj"/> parameter is null.
		/// </exception>
		public override bool Equals(object obj)
		{
			LogicalActivityBinding bind = obj as LogicalActivityBinding;
			if ( bind != null ) {
				return bind.LogicalActivityID == this.LogicalActivityID &&
					   bind.WebServiceID == this.WebServiceID &&
					   bind.WebMethodID == this.WebMethodID;
			} else {
				return false;
			}
		}
		/// <summary>
		/// Returns a hash code for this instance.
		/// </summary>
		/// <returns>
		/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
		/// </returns>
		public override int GetHashCode()
		{
			return base.GetHashCode();
		}
	}
	#endregion
}

